<?php

class HtmlElement
{
	private $above_children = true; ///< If context should be rendered above child elements
	private $attributes = array();
	private $element_name; ///< Tag name
	private $child_elements = array();
	private $context = ""; ///< Element context
	private $empty = false; ///< If the element is an empty element
	private $indent = 0;
	private $parent_element = null;

	function __toString()
	{
		return $this->renderElement();
	}

	function __construct($elem = "", HtmlElement &$parent = null, $empty_elem = false)
	{
		$this->setElementName($elem);

		if ($parent != null)
			$parent->addChildElement($this);

		$this->empty = $empty_elem;
	}

	function addChildElement(HtmlElement &$elem)
	{
		$elem->setParent($this);
		$elem->setIndent($this->indent+1);
		$this->child_elements[] = $elem;
		return $this;
	}

	function elementContext()
	{
		return $this->context;
	}

	function elementName()
	{
		return $this->element_name;
	}

	function parent()
	{
		return $this->parent_element;
	}

	function renderChildren()
	{
		$output = "";

		foreach ($this->child_elements as $child)
			$output .= $child->renderElement();

		return $output;
	}

	function renderContext()
	{
		$output = "";

		if ($this->above_children)
			$output .= $this->context;

		if (!empty($this->child_elements))
		{
			$output .= "\n";
			// $output .= str_repeat("\t", $this->indent);
			$output .= $this->renderChildren();
		}

		if (!$this->above_children)
			$output .= $this->context;

		return $output;
	}

	function renderElement()
	{
		return $this->renderStartingTag().$this->renderContext().$this->renderEndingTag();
	}

	function renderEndingTag()
	{
		$indent = (!empty($this->child_elements)) ? str_repeat("\t", $this->indent) : "";
		$id = (isset($this->attributes['id'])) ? "<!-- // ".$this->attributes['id']." -->" : "";
		return (!$this->empty) ? $indent."</".$this->element_name.">".$id."\n" : "\n";
	}

	function renderStartingTag()
	{
		$output = str_repeat("\t", $this->indent);
		$output .= "<".$this->element_name;

		foreach ($this->attributes as $key => $value)
			$output .= " ".$key."=\"".$value."\"";

		if ($this->empty)
			$output .= " />";
		else
			$output .= ">";

		return $output;
	}

	function setAttribute($attr, $value = "")
	{
		if ($attr != NULL)
		{
			if ($value == "")
				$value == (string) $attr;

			$this->attributes[$attr] = (string) $value;
		}

		else throw new BadMethodCallException('Attribute name not provided!');

		return $this;
	}

	function setContext($context = "")
	{
		if ($this->empty)
			throw new LogicException('Setting context to an empty element!');

		if ($context != "")
			$this->context = (string) $context;

		else throw new BadMethodCallException('Context not provided!');

		return $this;
	}

	function setElementName($elem = "")
	{
		if ($elem != "")
			$this->element_name = (string) $elem;

		else throw new BadMethodCallException('Tag name not provided!');

		return $this;
	}

	function setIndent($indent = 0)
	{
		$this->indent = (int) $indent;
		return $this;
	}

	function setParent(HtmlElement &$parent)
	{
		$this->parent_element = $parent;
		return $this;
	}
}

?>
